<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/12/11/0011
 * Time: 11:11
 */

namespace app\sports_admin\service;


use app\exception\DeviceLogException;
use app\exception\EquipmentException;
use app\exception\ParentsException;
use app\sports_admin\model\Parents;
use app\sports_admin\model\School;
use think\Config;
use think\Db;
use think\Exception;
use think\Request;
use app\sports_admin\model\Equipment as EquipmentModel;
use app\sports_admin\model\DeviceLog as DeviceLogModel;
use think\Loader;
use think\response\Json;

Loader::import('PHPExcel.Classes.PHPExcel');
Loader::import('PHPExcel.Classes.PHPExcel.IOFactory.PHPExcel_IOFactory');
Loader::import('PHPExcel.Classes.PHPExcel.Reader.Excel5');
class Equipment
{
    /**
     * 添加设备信息
     */
    public static function equipmentInsert()
    {
        $params = Request::instance()->param();
        self::findNumber($params['number']);
        if($params['type'] == 1){
            $params['parent_id'] = '';
        }else if($params['type'] == 2){
            $params['school_id'] = '';
        }
        $equipment = EquipmentModel::create([
            'number' => $params['number'],
            'serial_number' => $params['serial_number'],
            'device_batch' => $params['device_batch'],
            'school_id'=>$params['school_id'],
            'parent_id'=>$params['parent_id']
        ]);
        if(!$equipment){
            throw new EquipmentException([
                'msg'=>'设备信息添加失败',
                'errorCode'=>400
            ]);
        }
        return json(['code'=>201,'msg'=>'添加成功']);
    }
    /**
     * 更新设备信息
     * @param $id 设备信息id
     * @param $oldNumber 原设备编号
    */
    public static function updateEquipment()
    {
        $params = Request::instance()->param();
        if($params['type'] == 1){
            $params['parent_id'] = '';
        }else if($params['type'] == 2){
            $params['school_id'] = '';
        }
        $bool = (new EquipmentModel())->save(
            ['batch'=>$params['batch'],'serial_number'=>$params['serial_number'],'school_id'=>$params['school_id'],'parent_id'=>$params['parent_id']],['id'=>$params['id']]
        );
        if(!$bool){
            throw new EquipmentException([
                'msg'=>'修改失败',
                'errorCode'=>400
            ]);
        }
        return json(['code'=>200,'msg'=>'修改成功']);
    }
    /**
     * 获取参数
    */
    public static function requestParams()
    {
        //设备编号，序列号
        $params = Request::instance()->only(['number','serial_number']);
        return ['number'=>trim($params['number']),'serial_number'=>trim($params['serial_number'])];
    }
//    /**
//     * 添加设备信息
//     * @param $number 设备编号
//     * @param $serialNumber 设备序列号
//    */
//    public static function insert($number,$serialNumber)
//    {
//        $equipment = EquipmentModel::create([
//            'number' => $number,
//            'serial_number' => $serialNumber
//        ]);
//        if(!$equipment){
//            throw new EquipmentException([
//                'msg'=>'设备信息添加失败',
//                'errorCode'=>400
//            ]);
//        }
//        return $equipment->id;
//    }
//    /**
//     * 更新设备信息
//     * @param $id 设备信息id
//     * @param $number 设备编号
//     * @param $serialNumber 设备序列号
//     */
//    public static function update($id,$number,$serialNumber)
//    {
//        return EquipmentModel::where('id',$id)->update(['number'=>$number,'serial_number'=>$serialNumber]);
//    }
    /**
     * 查询设备编号是否存在
     * @param $number 设备编号
    */
    public static function findNumber($number)
    {
        $result = EquipmentModel::where('number',$number)->find();
        if($result){
            throw new EquipmentException([
                'msg'=>'设备编号已存在',
                'errorCode'=>400
            ]);
        }
        return true;
    }
    /**
     * 设备信息绑定
    */
    public static function equipmentBinding()
    {
        //绑定类型  1 家长绑定  2 学校绑定
        $type = intval(input('post.bindings'));
        if($type == 1){
            return self::parentsBinding();
        }else{
            return self::schoolBinding();
        }
    }
    /**
     * 家长绑定
    */
    public static function parentsBinding()
    {
        //设备信息id，需要绑定设备的信息(info)
        $params = Request::instance()->only(['id','info']);
        $parentsInfo = Parents::where('phone',trim($params['info']))->find();
        if(!$parentsInfo){
            throw new ParentsException([
                'msg'=>'手机号不存在',
                'errorCode'=>400
            ]);
        }
        $ids = explode(',',$params['id']);
        Db::startTrans();
        $bool = self::deviceBinding($ids,$parentsInfo);
        if(!$bool){
            Db::rollback();
            throw new Exception('服务器异常');
        }
        $bool = EquipmentModel::whereIn('id',$ids)->update(['parent_id'=>$parentsInfo->id]);
        if(!$bool){
            Db::rollback();
            throw new EquipmentException([
                'msg'=>'绑定失败',
                'errorCode'=>400
            ]);
        }
        Db::commit();
        return json(['code'=>200,'msg'=>'绑定成功']);
    }
    /**
     * 学校绑定
    */
    public static function schoolBinding()
    {
        //设备信息id，需要绑定设备的信息(info)
        $params = Request::instance()->only(['id','info']);
        $schoolInfo = School::where('school_name',trim($params['info']))->find();
        if(!$schoolInfo){
            throw new ParentsException([
                'msg'=>'学校名称不存在',
                'errorCode'=>400
            ]);
        }
        $ids = explode(',',$params['id']);
        Db::startTrans();
        $bool = self::deviceBinding($ids,$schoolInfo,$type=2);
        if(!$bool){
            Db::rollback();
            throw new Exception('服务器异常');
        }
        $bool = EquipmentModel::whereIn('id',$ids)->update(['school_id'=>$schoolInfo->school_id]);
        if(!$bool){
            Db::rollback();
            throw new EquipmentException([
                'msg'=>'绑定失败',
                'errorCode'=>400
            ]);
        }
        Db::commit();
        return json(['code'=>200,'msg'=>'绑定成功']);
    }
    /**
     * 设备解绑操作
    */
    public static function untying()
    {
        //解绑类型  1家长解绑 2学校解绑
        $type = intval(input('post.bindings'));
        if($type == 1){
            return self::parentUntying();
        }else{
            return self::schoolUntying();
        }
    }
    /**
     * 家长解绑操作
    */
    public static function parentUntying()
    {
        //设备信息id 数组类型[1,2,3....]
        $id = explode(',',input('post.id'));
        Db::startTrans();
        $bool = self::deviceUntying($id);
        if(!$bool){
            Db::rollback();
            throw new Exception('服务器异常');
        }
        $bool = EquipmentModel::whereIn('id',$id)->update(['parent_id'=>0]);
        if(!$bool){
            Db::rollback();
            throw new EquipmentException([
                'msg'=>'解绑失败',
                'errorCode'=>400
            ]);
        }
        Db::commit();
        return json(['msg'=>'解绑成功','code'=>201]);
    }
    /**
     * 学校解绑操作
     */
    public static function schoolUntying()
    {
        //设备信息id 数组类型[1,2,3....]
        $id = explode(',',input('post.id'));
        Db::startTrans();
        $bool = self::deviceUntying($id,$type=2);
        if(!$bool){
            Db::rollback();
            throw new Exception('服务器异常');
        }
        $bool = EquipmentModel::whereIn('id',$id)->update(['school_id'=>0]);
        if(!$bool){
            Db::rollback();
            throw new EquipmentException([
                'msg'=>'解绑失败',
                'errorCode'=>400
            ]);
        }
        Db::commit();
        return json(['msg'=>'解绑成功','code'=>201]);
    }

    /**
     * 设备绑定记录
     * @param Array $ids 设备id号
     * @param $type 1 家长绑定 2 学校绑定
    */
    public static function deviceBinding($ids,$info,$type=1)
    {
        $data = [];
        $equipmentInfo = EquipmentModel::whereIn('id',$ids)->select();
        if($type == 1){
            foreach($equipmentInfo as $key=>$value){
                $data[$key]['number'] = $value->number;
                $data[$key]['parent_phone'] = $info->phone;
            }
        }else{
            foreach($equipmentInfo as $key=>$value){
                $data[$key]['number'] = $value->number;
                $data[$key]['school_name'] = $info->school_name;
            }
        }
        $resultId = (new DeviceLogModel())->saveAll($data);
        if(!$resultId){
            throw new DeviceLogException([
                'msg' => '设备绑定记录添加失败',
                'errorCode' => 400
            ]);
        }
        return true;
    }
    /**
     * 设备解绑记录
     * @param Array $ids 设备id号
     * @param $type 1 家长绑定 2 学校绑定
    */
    public static function deviceUntying($ids,$type=1)
    {
        $data = [];
        if($type == 1){
            $info = EquipmentModel::with('parents')->select($ids);
            foreach($info as $key=>$value){
                $data[$key]['number'] = $value->number;
                $data[$key]['parent_phone'] = $value->parents->phone;
                $data[$key]['status'] = 2;
            }
            $resultId = (new DeviceLogModel())->saveAll($data);
            if(!$resultId){
                throw new DeviceLogException([
                    'msg' => '设备绑定记录添加失败',
                    'errorCode' => 400
                ]);
            }
        }else{
            $info = EquipmentModel::with('school')->select($ids);
            foreach($info as $key=>$value){
                $data[$key]['number'] = $value->number;
                $data[$key]['school_name'] = $value->school->school_name;
                $data[$key]['status'] = 2;
            }
            $resultId = (new DeviceLogModel())->saveAll($data);
            if(!$resultId){
                throw new DeviceLogException([
                    'msg' => '设备绑定记录添加失败',
                    'errorCode' => 400
                ]);
            }
        }
        return true;
    }
    /**
     * 批量导入设备信息
     */
    public static function importEquipmentInfo()
    {
        //上传的excel文件
        $file = request()->file('excel');
        $info = $file->validate(['ext' => 'xlsx,xls'])->move(ROOT_PATH . 'public' . DS . 'equipments');
        $exclePath = $info->getSaveName();  //获取文件名
        //上传文件的地址
        $filename = ROOT_PATH . 'public' . DS .'equipments'.DS.$exclePath;
        $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        if($extension == 'xlsx') {
            $objReader =\PHPExcel_IOFactory::createReader('Excel2007');
            //加载文件内容,编码utf-8
            $objPHPExcel = $objReader->load($filename, $encode = 'utf-8');
        }else if($extension == 'xls'){
            $objReader =\PHPExcel_IOFactory::createReader('Excel5');
            $objPHPExcel = $objReader->load($filename, $encode = 'utf-8');
        }
        //转换为数组格式
        $excel_array = $objPHPExcel->getsheet(0)->toArray();
        //删除第一个数组(标题);
        array_shift($excel_array);
        $data = [];
        foreach($excel_array as $k=>$v) {
            $data[$k]['number'] = $v[0];
            $data[$k]['serial_number'] = $v[1];
        }
        $bool = (new EquipmentModel())->saveAll($data);
        if(!$bool){
            throw new EquipmentException([
                'msg'=>'导入失败',
                'errorCode'=>400
            ]);
        }
        return json(['code'=>200,'msg'=>'导入成功']);
    }
    /**
     * 下发编号
     */
    public static function lowerNumber()
    {
        //获取参数
        $params = Request::instance()->param();
        $data = EquipmentModel::where('device_batch',$params['batch'])->select();
        foreach ($data as $key=>$value){
            $arr[$key]['number'] = $value->number;
            $arr[$key]['serialNumber'] = "3-76-2-99-{$key}";
        }
        $info['info']['number'] = $arr;
        $info['info']['instructions']= 'number';
        $info['info']['uid']= 1;
        //要加密的签名
        $info['info']['skin'] = getRandChar(15);
        //获取秘钥
        $key = Config::get('skin');
        //签名
        $info['info']['token'] = authcode($info['info']['skin'],'ENCODE',$key['key'],0);
        // 推送的数据，设备编号字段
        $data = $info['info'];
        $client = stream_socket_client('tcp://39.105.192.86:5679', $errno, $errmsg, 1);
        //发送数据，注意5679端口是Text协议的端口，Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($data)."\n");
        $returnInfo = json_decode(fread($client, 8192),true);
        return $returnInfo;
    }
    /**
     * 下发开启检测模式
     */
    public static function openMonitoring()
    {
        $temArray = [];
        //获取参数
        $params = Request::instance()->param();
        $data = EquipmentModel::where('device_batch',$params['batch'])->select();
        foreach ($data as $key=>$value){
            $arr['number'] = $value->number;
            $arr['high'] = '40';
            $arr['low'] = '20';
            $temArray[] = $arr;
        }
//        var_dump($temArray);
//        exit();
        $info['info']['number'] = $temArray;
        $info['info']['instructions']= 'monitoring';
        $info['info']['status']= 'open';
        $info['info']['uid']= 1;
        //要加密的签名
        $info['info']['skin'] = getRandChar(15);
        //获取秘钥
        $key = Config::get('skin');
        //签名
        $info['info']['token'] = authcode($info['info']['skin'],'ENCODE',$key['key'],0);
        // 推送的数据，设备编号字段
        $data = $info['info'];
       // return json_encode(['data'=>$data]);
        $client = stream_socket_client('tcp://39.105.192.86:5679', $errno, $errmsg, 1);
        //发送数据，注意5679端口是Text协议的端口，Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($data)."\n");
        $returnInfo = json_decode(fread($client, 8192),true);
        return $returnInfo;
    }
    /**
     * 下发关闭检测模式
     */
    public static function closeMonitoring()
    {
        //获取参数
        $params = Request::instance()->param();
        $data = EquipmentModel::where('device_batch',$params['batch'])->select();
        foreach ($data as $key=>$value){
            $arr[] = $value->number;
        }
        $info['info']['number'] = $arr;
        $info['info']['instructions']= 'monitoring';
        $info['info']['status']= 'close';
        $info['info']['uid']= 1;
        //要加密的签名
        $info['info']['skin'] = getRandChar(15);
        //获取秘钥
        $key = Config::get('skin');
        //签名
        $info['info']['token'] = authcode($info['info']['skin'],'ENCODE',$key['key'],0);
        // 推送的数据，设备编号字段
        $data = $info['info'];
        $client = stream_socket_client('tcp://39.105.192.86:5679', $errno, $errmsg, 1);
        //发送数据，注意5679端口是Text协议的端口，Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($data)."\n");
        $returnInfo = json_decode(fread($client, 8192),true);
        return $returnInfo;
    }
}